#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "ctrl_reg.h"
#include <cstring>


int gpio_setup(gpio_handle *handle, unsigned int baseAddr) {
    handle->baseAddr=baseAddr;
    handle->gpioHandler = open("/dev/mem", O_RDWR | O_SYNC);
    handle->gpioVirtualAddress = (unsigned int*)mmap(NULL, 65535, PROT_READ | PROT_WRITE, MAP_SHARED, handle->gpioHandler, (off_t)handle->baseAddr);
    if(handle->gpioVirtualAddress == MAP_FAILED) {
        perror("gpioVirtualAddress mapping for absolute memory access failed.\n");
        return -1;
    }
    else
        return 0;
}

void gpio_set(gpio_handle *handle, int num, unsigned int val){
    handle->gpioVirtualAddress[num>>2]=val;
}

int gpio_get(gpio_handle *handle, int num){
    return handle->gpioVirtualAddress[num>>2];
}

void camera_close(gpio_handle *handle, unsigned int id){
    gpio_set(handle,OFFSET_CAMERA_CONTROL,id);
}

void camera_open(gpio_handle *handle, unsigned int id){
    gpio_set(handle,OFFSET_CAMERA_CONTROL,id);
}

void camera_exp_period(gpio_handle *handle, int num1, int num2){
    gpio_set(handle,OFFSET_CAMERA_EXP_LOW32bit,num1);
    gpio_set(handle,OFFSET_CAMERA_EXP_HIGH32bit,num2);
}

void camera_exp_2us(gpio_handle *handle){
    gpio_set(handle,OFFSET_CAMERA_EXP_CTRL,0x0);
}

void camera_exp_set_us(gpio_handle *handle){
    gpio_set(handle,OFFSET_CAMERA_EXP_CTRL,0x1);
}

void camera_exp_set_us_stop(gpio_handle *handle){
    gpio_set(handle,OFFSET_CAMERA_EXP_CTRL,0x2);
}

void camera_adc_set_ctrl(gpio_handle *handle,int adc_ctrl,int slave_id){
    int status=0;
    gpio_set(handle,OFFSET_CAMERA_ADC_CTRL,0x0);
    while(!status){
        status = ((iic_status(handle) & 0xff000000) == 0x0);
    }
    gpio_set(handle,OFFSET_CAMERA_ADC_CTRL,(0x80000000 | (adc_ctrl & 0xff) << 8) | ((slave_id & 0x7f) << 1));
}

void camera_adc_set_read(gpio_handle *handle,int slave_id){
    gpio_set(handle,OFFSET_CAMERA_ADC_CTRL,(0x80000000 | ((slave_id & 0x7f) << 1) | 0x1));
}

void camera_adc_period(gpio_handle *handle, int num){
    gpio_set(handle,OFFSET_CAMERA_SAMPLE_RATE,num);
}


int id_value(gpio_handle *handle){
    return gpio_get(handle,OFFSET_ID_VALUE);
}

int adc_ctrl_reg(gpio_handle *handle){
    return gpio_get(handle,OFFSET_ADC_VALUE) & 0xFF;
}

int adc_value(gpio_handle *handle){
    return (gpio_get(handle,OFFSET_ADC_VALUE) >> 8 ) & 0xFFFF;
}

int iic_status(gpio_handle *handle){
    return (gpio_get(handle,OFFSET_ADC_VALUE) >> 24 ) & 0xFF;
}

int camera_exp_status(gpio_handle *handle){
    return gpio_get(handle,OFFSET_EXP_STATUS) & 0x1;
}




